package org.dromara.module.api;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.lock.LockInfo;
import com.baomidou.lock.LockTemplate;
import com.baomidou.lock.executor.RedissonLockExecutor;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vdurmont.emoji.EmojiParser;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.ResponseCode;
import org.dromara.common.core.utils.GsonResultBean;
import org.dromara.common.core.utils.OrderUtil;
import org.dromara.common.core.utils.Tools;
import org.dromara.module.domain.Product;
import org.dromara.module.domain.ProductOrder;
import org.dromara.module.domain.WxMsgTemplate;
import org.dromara.module.domain.WxUser;
import org.dromara.module.service.IProductOrderService;
import org.dromara.module.service.IProductService;
import org.dromara.module.service.IWxUserService;
import org.dromara.module.wxpay.RSA;
import org.dromara.module.wxpay.WXPayCommonUtil;
import org.dromara.module.wxpay.WxAppPay;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.*;

/**
 *@Author: ZhouWei
 *@Description:  订单列表
 *@Date 2018-05-10
 */
@SaIgnore
@Slf4j
@RestController
@RequestMapping("/api/pay")
public class PayController {

    @Resource
    private IProductOrderService productOrderService;
    @Resource
    private IProductService productService;
    @Resource
    private IWxUserService wxUserService;
    @Resource
    protected RedisTemplate<String, Object> redisTemplate;

    @Value("${wx.wx_notify_url}")
    private String wx_notify_url;//微信支付的回调地址

    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.secret}")
    private String secret;

    @Value("${wx.mch_id}")
    private String mch_id;
    @Value("${wx.v2key}")
    private String api_key;

    @Resource
    private LockTemplate lockTemplate;

    /**
     * 调起支付
     * @return
     */
    @PostMapping(value = "/test")
    public JSONObject test(@RequestBody String requestParam, HttpServletRequest request){
        JSONObject ret = null;
        try{
            JSONObject jsonRequest = JSONUtil.parseObj(requestParam);
            int user_id = jsonRequest.containsKey("user_id") ? jsonRequest.getInt("user_id") : 0;
            long order_id = jsonRequest.containsKey("order_id") ? jsonRequest.getInt("order_id") : 0L;

            return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"成功"),true,true);

        }catch (Exception e){
            e.printStackTrace();
        }
        return ret;
    }
    /**
     * 微信小程序调起支付
     * @return
     */
    @PostMapping(value = "/requestPay")
    public JSONObject requestPay(@RequestBody String requestParam, HttpServletRequest request){
        JSONObject ret = null;
        if(StrUtil.isEmpty(requestParam)){
            return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"参数异常"),true,true);
        }
        JSONObject jsonRequest = JSONUtil.parseObj(requestParam);
        int user_id = jsonRequest.containsKey("user_id") ? jsonRequest.getInt("user_id") : 0;
        long order_id = jsonRequest.containsKey("order_id") ? jsonRequest.getInt("order_id") : 0L;


        LockInfo lockInfo = lockTemplate.lock(order_id + "_requestPay", 30000L, 5000L, RedissonLockExecutor.class);
        if (lockInfo == null) {
            return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"业务处理中,请稍后再试"),true,true);
        }

        try{
            String subject = jsonRequest.containsKey("subject") ? jsonRequest.getStr("subject") : "";
            String remark = jsonRequest.containsKey("remark") ? jsonRequest.getStr("remark") : null;
            int address_id = jsonRequest.containsKey("address_id") ? jsonRequest.getInt("address_id") : 0;

            String orderNo = "";
            boolean blIsMineOrder = false;


            WxUser user = wxUserService.getById(user_id);
            if(user == null){
                return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该用户不存在"),true,true);
            }

            ProductOrder orders = productOrderService.getById(order_id);
            if(orders != null){
                int orderUserId = orders.getUserId();
                if(orderUserId == user_id){
                    orderNo = orders.getOutTradeNo();
                    blIsMineOrder = true;
                }else{
                    blIsMineOrder = false;
                }

                Product product = productService.getProductByOrderId(order_id);
                if(product!= null){
                    if(product.getIsSaleOut() == 1){
                        return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL, "该商品已售罄"), true, true);
                    }
                }

                if(orders.getStatus() == 0 || orders.getStatus() == 1){//如果是 再次提交支付的话，订单号要生成新的
                    orderNo = OrderUtil.getOrderNoByTimespan();
                    orders.setOutTradeNo(orderNo);
                }else if(orders.getStatus() == 2 || orders.getStatus() == 3 || orders.getStatus() == 4){
                    /**
                     * 订单状态 0 - 未支付   1 - 支付中  2 - 已支付（待核销）  3 - 已核销  4 - 已评价
                     * 5 - 订单取消  6 - 发起退货  7 - 同意退货  8 - 退货完成  9 - 拒绝退货  10 - 团购成功 11 - 团购失败
                     */
                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"订单已支付"),true,true);
                } else if(orders.getStatus() == 5){
                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"订单已取消"),true,true);
                }
                else{
                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"当前状态不能发起支付"),true,true);
                }

                if(StrUtil.isNotEmpty(remark)){
                    orders.setRemark(remark);
                }
            }

            if(blIsMineOrder){
                if(orders.getPayPrice().doubleValue() > 0) {
                    WxAppPay wxAppPay = new WxAppPay(wx_notify_url, secret, appid, mch_id, api_key);
                    String retRequest = wxAppPay.weiXinPrePay(orderNo, orders.getPayPrice(), subject, request.getRemoteAddr(), user.getOpenId(), "NORMAL");
                    ret = Tools.getJson(new GsonResultBean<>(ResponseCode.OK, "请求成功", retRequest), true, false);
                    orders.setStatus(1);//支付中
                    productOrderService.updateById(orders);
                }else{
                    JSONObject retData = new JSONObject();
                    retData.set("result_code", "NOTNEEDPAY");
                    ret = Tools.getJson(new GsonResultBean<>(ResponseCode.OK, "请求成功"), true, false);
                    orders.setStatus(2);//无需支付的情况，抵扣完了
                    productOrderService.buyNormalUpdate(orders,user);
                }

            }else{//当前订单不属于您
                ret = Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"当前订单不属于您"),true,true);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放锁
            lockTemplate.releaseLock(lockInfo);
        }
        return ret;
    }

    /**
     * 调起退款(发起退款操作)
     * @return
     */
    @PostMapping(value = "/requestRefund")
    public JSONObject requestRefund(@RequestBody String requestParam, HttpServletRequest request){
        JSONObject ret = null;
        try{
            if(StrUtil.isEmpty(requestParam)){
                return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"参数异常"),true,true);
            }
            JSONObject jsonRequest = JSONUtil.parseObj(requestParam);
            int user_id = jsonRequest.containsKey("user_id") ? jsonRequest.getInt("user_id") : 0;
            long order_id = jsonRequest.containsKey("order_id") ? jsonRequest.getInt("order_id") : 0L;
            String reason = jsonRequest.containsKey("reason") ? jsonRequest.getStr("reason") : "";

            boolean blIsMineOrder = false;
            WxUser user = wxUserService.getById(user_id);
            if(user == null){
                return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该用户不存在"),true,true);
            }


            return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"请联系客服退款"),true,true);

//            PlatformPay platformPay = platformPayService.getDefaultAccount();
//
//            ProductOrder orders = productOrderService.findById(order_id);
//            if(orders != null){
//                orders.setRefundReasonWapExplain(reason);
//
//                if(orders.getUserId().intValue() != user_id){
//                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该订单不属于你"),true,true);
//                }
//
//                if(orders.getIsMerCheck() == 1){
//                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该订单已核销，不能发起退款"),true,true);
//                }
//
//                if(orders.getStatus() == 7){
//                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该订单在退款中请耐心等待"),true,true);
//                } else if(orders.getStatus() == 8){
//                    return Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该订单已退款完成"),true,true);
//                }
//
//                blIsMineOrder = true;
//                String out_refund_no = OrderUtil.getOrderNoByTimespan();
//                orders.setRefundOutTradeNo(out_refund_no);
//
//                if(orders.getStatus() == 2){
//                    if(blIsMineOrder) {
//                        if(orders.getPayType() == 0) {
//                            WxAppPay wxAppPay = new WxAppPay(wx_refund_notify_url, secret, appid, mch_id, api_key);
//                            String retRequest = wxAppPay.refundPayAPI(orders.getOutTradeNo(), orders.getPayPrice(), orders.getPayPrice(), orders.getRefundOutTradeNo(), keyPath);
//                            ret = Tools.getJson(new GsonResultBean<>(ResponseCode.OK, "请求成功", retRequest), true, false);
//
//                            //订单状态 0 - 未支付   1 - 支付中  2 - 已支付（待核销）  3 - 已核销
//                            // 4 - 已评价  5 - 订单取消  6 - 发起退货  7 - 同意退货(退货处理中)  8 - 退货完成  9 - 拒绝退货
//                            orders.setStatus(7);//同意退货
//                            productOrderService.updateById(orders);
//                        }else{
//                            //String out_trade_no, BigDecimal refund_money, String out_refund_no,PlatformPay platformPay
//                            String retRequest = platformPayService.refundOrder(orders.getOutTradeNo(), orders.getPayPrice(),orders.getRefundOutTradeNo(),platformPay);
//                            System.out.println("PayController requestRefund 退款查询响应: " + retRequest);
//                            JSONObject jsonObject = JSONUtil.parseObj(retRequest);
//                            if(jsonObject!=null){
//                                String errCode = jsonObject.getStr("errCode");
//                                String errMsg = jsonObject.getStr("errMsg");
//                                String refundStatus = jsonObject.getStr("refundStatus");
//                                if(errCode.equals("SUCCESS") && refundStatus.equals("SUCCESS")){
//                                    ret = Tools.getJson(new GsonResultBean<>(ResponseCode.OK,"请求成功"),true,false);
//                                    orders.setStatus(7);//同意退货
//                                    productOrderService.updateById(orders);
//                                }else{
//                                    ret = Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,errMsg),true,true);
//                                }
//                            }
//                        }
//                    }else{//当前订单不属于您
//                        ret = Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"当前订单不属于您"),true,true);
//                    }
//                }else{//当前订单不属于您
//                    ret = Tools.getJson(new GsonResultBean<>(ResponseCode.FAIL,"该状态下不能发起退款"),true,true);
//                }
//            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return ret;
    }

    /**
     * 微信支付成功回调处理
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/wxpay_notify")
    public String wxpayProductNotify(HttpServletRequest request) throws IOException {
        System.out.println("微信支付回调");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        int ret = 0;
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultXml = new String(outSteam.toByteArray(), "utf-8");
        System.out.println("微信支付回调:" + resultXml);
        Map<String, String> params = null;
        try {
            params = WXPayCommonUtil.doXMLParse(resultXml);
        } catch (JDOMException e) {
            e.printStackTrace();
        }
        outSteam.flush();
        outSteam.close();
        inStream.close();
        if (!WXPayCommonUtil.isTenpaySign(params,api_key)) {
            // 支付失败
            return "fail";
        } else {
            System.out.println("===============付款成功==============");
            // ------------------------------
            // 处理业务开始
            // ------------------------------
            // 此处处理订单状态，结合自己的订单数据完成订单状态的更新
            // ------------------------------
            String result_code = params.get("result_code");
            String attach = params.get("attach");
            System.out.println("附加信息: " + attach);
            try {
                if(attach.equals("NORMAL")){//普通商品订单
                    ret = pay_success_product(params,result_code,1);//逻辑处理
                }

                if(ret > 0){
                    return "success";
                }else{
                    return "fail";
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 处理业务完毕
            // ------------------------------
            return "fail";
        }
    }

    /**
     * 商品订单的   成功之后的 业务处理
     * @param params
     * @param trade_status
     * @param payType
     * @return
     */
    @SuppressWarnings("unchecked")
    private int pay_success_product(Map<String, String> params,String trade_status,int payType){
        String out_trade_no = "";// 本平台  商户订单号
        if(params.containsKey("merOrderId")){
            out_trade_no = params.get("merOrderId");// 本平台  商户订单号
        } else if(params.containsKey("out_trade_no")){
            out_trade_no = params.get("out_trade_no");// 本平台  商户订单号
        }
        int ret = 0;
        try{
            QueryWrapper<ProductOrder> qw = new QueryWrapper<>();
            qw.eq("out_trade_no",out_trade_no).or().eq("order_no",out_trade_no);
            ProductOrder order = productOrderService.getOne(qw);
            if(order != null){
                WxUser user = wxUserService.getById(order.getUserId());
                if(order.getStatus() == 0 || order.getStatus() == 1 || order.getStatus() == 5) {//支付中的 状态 才往下执行
                    String total_amount = "";//  订单金额
                    String trade_no = "";//  订单号
                    double total_amount_double = 0;
                    String payTime = "";
                    if (trade_status.equals("SUCCESS") || trade_status.equals("TRADE_SUCCESS")) {
                        if (payType == 0) {//支付宝支付参数
                            total_amount = params.get("total_amount");
                            trade_no = params.get("trade_no");//支付宝支付订单号
                            total_amount_double = Double.valueOf(total_amount);
                        } else if (payType == 1) {//微信支付参数
                            total_amount = params.get("total_fee");
                            trade_no = params.get("transaction_id");//微信支付订单号
                            total_amount_double = Double.valueOf(total_amount) / 100;
                            payTime = params.get("time_end");
                        } else if (payType == 2) {// 农商行 支付参数
                            total_amount = params.get("totalAmount");
                            trade_no = params.get("targetOrderId");//微信支付订单号
                            total_amount_double = Double.valueOf(total_amount) / 100;
                            payTime = params.get("payTime");
                        }

                        //订单状态 0 - 未支付   1 - 支付中  2 - 已支付（待核销）  3 - 已核销
                        // 4 - 已评价  5 - 订单取消  6 - 发起退货  7 - 同意退货  8 - 退货完成  9 - 拒绝退货
                        order.setStatus(2);
                        order.setTransactionId(trade_no);
                        order.setPayPrice(new BigDecimal(total_amount_double));
                        order.setPayTime(new Date());
                        ret = productOrderService.buyNormalUpdate(order,user);
                        if(ret > 0){
                            //支付成功通知
                            //String merName, String phoneNum, String productName
                        }
                    }
                }
            }else{
                System.out.println("普通商品订单号：" + out_trade_no + "不存在");
                log.error("普通商品订单号：" + out_trade_no + "不存在");
            }
        }catch (Exception ex){
            ex.printStackTrace();
            System.out.println(""+ex.getMessage());
        }
        return ret;
    }

    /**
     * 微信支付退款回调处理
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/wxpay_refund_notify")
    public String wxPayRefundNotify(HttpServletRequest request) throws IOException {
        System.out.println("微信支付退款回调");
        InputStream inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        int ret = 0;
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        String resultXml = new String(outSteam.toByteArray(), "utf-8");
        System.out.println("微信退款处理成功回调:" + resultXml);
        Map<String, String> params = null;
        try {
            params = WXPayCommonUtil.doXMLParse(resultXml);
        } catch (JDOMException e) {
            throw new RuntimeException(e);
        }
        outSteam.flush();
        outSteam.close();
        inStream.close();
        System.out.println("===============退款处理成功==============");
        // ------------------------------
        // 处理业务开始
        // ------------------------------
        // 此处处理订单状态，结合自己的订单数据完成订单状态的更新
        // ------------------------------
        String return_code = params.get("return_code");
        String attach = params.get("attach");
        System.out.println("附加信息: " + attach);
        String req_info = params.get("req_info");
        try {
            if(return_code.equals("SUCCESS")){
                String descrypt = RSA.descrypt(req_info,api_key);
                Map<String,String> reqInfoMap = WXPayCommonUtil.doXMLParse(descrypt);
                ret = refund_success_product(reqInfoMap,1);
                if(ret > 0){
                    return "success";
                }else{
                    return "fail";
                }
            }
            return "fail";
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 处理业务完毕
        // ------------------------------
        return "fail";
    }

    /**
     * 商品订单的 退款成功处理
     * @param params
     * @return
     */
    @SuppressWarnings("unchecked")
    private int refund_success_product(Map<String, String> params,int payType){
        String out_trade_no = params.get("out_trade_no");// 本平台  商户订单号
        if(payType == 2){
            out_trade_no = params.get("merOrderId");// 本平台  商户订单号
        }
        System.out.println("商品退款订单的订单号：" + out_trade_no + "，退款回调");
        int ret = 0;
        try{
            QueryWrapper<ProductOrder> qw = new QueryWrapper<>();
            qw.eq("out_trade_no",out_trade_no).or().eq("order_no",out_trade_no);
            ProductOrder order = productOrderService.getOne(qw);
            if(order != null){
                WxUser user = wxUserService.getById(order.getUserId());
                if(order.getStatus() == 7) {//发起退款 并同意申请 的才执行
                    String refund_fee = "";//  订单金额
                    String trade_no = "";//  订单号
                    double refund_fee_double = 0;

//                    refund_fee = params.get("refund_fee");
//                    trade_no = params.get("transaction_id");//微信支付订单号
//                    refund_fee_double = Double.valueOf(refund_fee) / 100;

                    if (payType == 0) {//支付宝支付参数
                        refund_fee = params.get("refund_fee");
                        trade_no = params.get("transaction_id");//微信支付订单号
                        refund_fee_double = Double.valueOf(refund_fee) / 100;
                    } else if (payType == 1) {//微信支付参数
                        refund_fee = params.get("refund_fee");
                        trade_no = params.get("transaction_id");//微信支付订单号
                        refund_fee_double = Double.valueOf(refund_fee) / 100;
                    } else if (payType == 2) {// 农商行 支付参数
                        refund_fee = params.get("refundAmount");
                        refund_fee_double = Double.valueOf(refund_fee) / 100;
                        trade_no = params.get("targetOrderId");//微信支付订单号
                    }


                    //订单状态 0 - 未支付   1 - 支付中  2 - 已支付（待核销）  3 - 已核销
                    // 4 - 已评价  5 - 订单取消  6 - 发起退货  7 - 同意退货  8 - 退货完成  9 - 拒绝退货
                    order.setStatus(8);
                    order.setTransactionId(trade_no);
                    order.setRefundStatus(2);
                    order.setRefundPrice(new BigDecimal(refund_fee_double));
                    order.setRefundReasonTime(new Date());
                    ret = productOrderService.buyNormalUpdate(order,user);
                    if(ret > 0){
                        //退款成功通知
                    }
                }
            }else{
                System.out.println("普通商品订单号：" + out_trade_no + "不存在");
                log.error("普通商品订单号：" + out_trade_no + "不存在");
            }
        }catch (Exception ex){
            ex.printStackTrace();
            System.out.println(ex.getMessage());
        }
        return ret;
    }

}
